/**
 * 平面位置
 */
export interface Point2D {
  x: number;
  y: number;
}

/**
 * 平面大小
 */
export interface Size2D {
  xb: number;
  yb: number;
}

/**
 * 平面大小和位置
 */
export interface SizeAndPoint2D extends Size2D, Point2D {
}

export interface SizeAndPoint1D {
  x: number;
  xb: number;
}


export class PointUtils {

  /**
   * 中心点计算到生成物体的位置，
   * 动态计算，
   * @param center 参考的中心节点
   * @param size 生成物体的大小
   * @param others 在这个参考中心中，其他物体的信息，x为中心点
   */
  static getPoint1DByCenterPoint1DAndSize1D(center: number, size: number, others: SizeAndPoint1D[]): number {
    let result: number | undefined = undefined;
    let length: number = 0;
    if (!others.length) {
      return center
    }
    others = others
      // 整理位置信息，从小到大排序
      .sort((a, b) => {
        return a.x - b.x
      })
    const pos = others
      // 获取所有线段的位置
      .map(i => {
        const number = i.xb / 2;
        return [i.x - number, i.x + number]
      })
      // 过滤重叠部位
      .reduce((a, b) => {
        if (a.length) {
          const result: number[][] = []
          for (let i = 0; i < a.length; i++) {
            let overlap = false
            const item = a[i]
            const length = Math.abs(item[0] - item[1])
            if (Math.abs(b[0] - item[0]) < length) { // 左边有重叠
              b[0] = Math.min(b[0], item[0])
              overlap = true
            }
            if (Math.abs(b[1] - item[1]) < length) { // 右边有重叠
              b[1] = Math.min(b[1], item[1])
              overlap = true
            }
            if (!overlap) {
              result.push(item)
            }
          }
          result.push(b)
          return result
        } else {
          a.push(b)
          return a
        }
      }, [] as number[][])
    // 计算中间位置
    if (pos.length >= 2) {
      // 获取所有可以插入的位置
      for (let i = 0; i < pos.length - 1; i++) {
        const left_right = pos[i][1] // 节点的右边
        const right_left = pos[i + 1][0] // 下一个节点的左边
        if (Math.abs(left_right - right_left) >= size) { // 可以插入的位置
          if (result === undefined) {
            result = (left_right - right_left) / 2
          } else {
            const now1 = (left_right - right_left) / 2
            if (now1 - center < length) {
              result = now1
            }
          }
          length = Math.abs(result - center)
        }
      }
    }
    // 计算两边
    const left = pos[0][0]
    const left1 = left - size
    const leftC = (left1 + left) / 2
    const leftL = Math.abs(leftC - center)
    if (leftL < length) {
      length = leftL
      result = leftC
    }
    const right = pos[pos.length - 1][1]
    const right1 = right + size
    const rightC = (right1 + right) / 2
    const rightL = Math.abs(rightC - center)
    if (rightL < length) {
      result = rightC
    }
    if (result) {
      return result
    } else {
      return 0
    }
  }

  /**
   * 中心点计算到生成物体的位置，用半径计算，
   * 动态计算，
   * @param center 参考的中心节点
   * @param size 生成物体的大小
   * @param others 在这个参考中心中，其他物体的信息，x，y为中心点
   */
  static generatePointByCenterPointAndOtherPointAndSize(center: Point2D, size: Size2D, others: SizeAndPoint2D[]): Point2D {
    if (!others.length) {
      return center
    }
    return {
      x: PointUtils.getPoint1DByCenterPoint1DAndSize1D(center.x, size.xb, others.map(i => {
        return {
          x: i.x,
          xb: i.xb
        }
      })),
      y: PointUtils.getPoint1DByCenterPoint1DAndSize1D(center.y, size.yb, others.map(i => {
        return {
          x: i.y,
          xb: i.yb
        }
      }))
    }
  }
}
